import { NSpace, NTable, NPagination, NDatePicker,NCheckbox, NTreeSelect  } from 'naive-ui'
import MetaHeader from '/src/components/vue-meta/meta-header.vue'
import roleApi from '/src/api/base/role_api.js'
import permissionApi from '/src/api/base/permission_api.js'
import rolePermissionApi from '/src/api/base/role-permission_api.js'


import { parseTime } from '/src/utils/tools.js'

const dialogForm = () => {
  return {
    name: '',
    roleCode: '',
  }
}

// 权限格式转 tree 选项的格式
function convertToTreeOptionArray(arr) {
  if(!arr) {
    return arr
  }
  let re = []
  for(let i=0; i<arr.length; i++) {
    let child = convertToTreeOption(arr[i])
    re.push(child)
  }
  return re
}
function convertToTreeOption(pvo) {
  // let obj = { key: pvo.id+"", label: pvo.code }
  let obj = { key: pvo.code, label: pvo.description ? pvo.description : pvo.code }
  if(pvo.children && pvo.children.length>0) {
    obj.children = convertToTreeOptionArray(pvo.children)
  }
  return obj
}

// 根据 code 找到 tree 选项中的节点
function findTreeNodeInArray(arr, key) {
  if(!arr || arr.length==0) {
    return null
  }

  for(let i=0; i<arr.length; i++) {
    let t = arr[i]
    if(t.key == key) {
      return t
    }

    if(t.children && t.children.length>0) {
      let childResult= findTreeNodeInArray(t.children, key)
      if(childResult) {
        return childResult
      }
    }
  }
  return null
}
// 把节点的和其的 children 的 key 转成一维 list
function getKeysInTreeNodeArr(arr) {
  let re = []
  if(!arr || arr.length==0) {
    return re
  }

  for(let i=0; i<arr.length; i++) {
    let t = arr[i]
    if(!t) { continue }
    re.push(t.key)

    if(t.children && t.children.length>0) {
      let childkeys = getKeysInTreeNodeArr(t.children)
      if(childkeys && childkeys.length>0) {
        re = re.concat(childkeys)
      }
    }
  }

  return re
}

export default {
  components: { NSpace, NTable, NPagination, NDatePicker, NCheckbox, NTreeSelect, MetaHeader,  },
  inject: [ "Message", "Dialog" ],
  props: {
    // 是否是从其他组件中掉起此组件
    isModalComponent: { type: Boolean, default: ()=> false },
  },
  data() {
    return {
      datas: [],
      tableLoading: false,

      search: {
        name: null,
      },

      tableCheckList: {}, // 不是数组, key 是选中的下标, value 是否选中 
      tablePage: {
          page: 1,
          size: 10,
          total: 0,
      },

      // 弹出层
      showModal: false,
      isEdit: false,
      dialogFormSaving: false,
      dialogForm: dialogForm(),
      rules: {
          rules: {
              name: [ { required: true, message: '角色名字！',trigger: ['blur'] } ],
              roleCode: [ { required: true, message: '角色唯一代码',trigger: ['blur'] } ],
          }    
      },

      // 分页候选项
      pageSizeOption: [ {label: '10/页', value:10 }, {label: '20/页', value:20 }, {label: '30/页', value:30 } ],
      // pageSizeOption: [ {label: '1/页', value:1 }, {label: '2/页', value:2 }, {label: '3/页', value:3 } ]

      // 后端返回的完整权限树
      permissionTree: [],
      // 权限弹窗
      permissionDialog: {
        visible: false,
        loading: false,
        role: null,
        permissionTreeOption: [],
        // 选择的权限，最终上传给后台保存
        permissions: [],
        // 旧权限，打开选择框前的权限
        oldPermissions: []
      },

      // 权限树刷新按钮
      permissionTreeRefreshing: false,
      // 刷新权限按钮
      rolePermissionRefreshing: false,
    }
  },
  computed: {
    // 表格全选状态
    tableAll() {
      let len = this.datas?.length
      if(len == 0){
        return false
      }
      for(let i=0; i<len; i++) {
        if(!this.tableCheckList[i]) {
          return false
        }
      }
      // 全选中
      return true
    },
    // 表格半选状态
    tableIndeterminate() {
      if(this.tableAll) {
        return false
      }

      let len = this.datas?.length
      for(let i=0; i<len; i++) {
        if(this.tableCheckList[i]) {
          return true
        }
      }
      // 全没选中
      return false
    },
  },
  watch: {
    tableCheckList(newVal,oldVal) {
      //console.log("watch", newVal)
    }
  },
  created() {
    // this.datas = [
    //   { no: 1, code: 'Hello', description: '3:21' },
    //   { no: 2, code: 'Roll with It', description: '3:59' },
    // ]

    this.listData()
    this.queryPermissionTree()
  }, 
  methods: {
    parseTime(datetimeStr, formatter) {
      return parseTime(new Date(datetimeStr), formatter)
    },

    // ==弹窗==
    // 新增
    showAdd() {
      this.isEdit = false
      this.showModal = true
      this.dialogForm = dialogForm()
    },
    showEdit(obj) {
      this.isEdit = true
      this.showModal = true

      let cpObj = Object.assign({}, obj)
      this.dialogForm = cpObj
    },
    close() {
      this.showModal = false
    },
    reset() {
      this.dialogForm = dialogForm()
      this.dialogFormSaving = false
    },

    // 页码变化
    pageChange(page) {
      // console.log("page", page)
      this.tablePage.page = page
      this.listData()
    },
    // 页大小变化
    pageSizeChange(pageSize) {
      // console.log("pageSize", pageSize)
      this.tablePage.page = 1
      this.tablePage.size = pageSize
      this.listData()
    },
    // 切换选中状态
    toggleCkeckAll() {
      // console.log("tableCheckList", this.tableAll, this.tableIndeterminate, this.tableCheckList)
      if(this.tableIndeterminate) { // 部分选 => 全选
          this.setCheckAll(true)
      } else if(this.tableAll) { // 全选 => 不选
          this.setCheckAll(false)
      } else { // 其他 => 全选
          this.setCheckAll(true)
      }
    },
    // 设置全选或取消全选
    setCheckAll(isCheck) {
      let len = this.datas?.length
      for(let i=0; i<len; i++) {
        this.tableCheckList[i] = isCheck
      }
    },
    // 当前页选中的数据
    listSelectedDatas() {
      let arr = []
      if(!this.datas) {
          return arr
      }

      let keys = Object.keys(this.tableCheckList)
      //console.log("this.tableCheckList", this.tableCheckList)
      for(let i=0; i<keys.length; i++) {
          let key = keys[i]
          if(this.tableCheckList[key]) {
              arr.push(this.datas[key])
          }
      }

      return arr.filter(e => e)
    },

    // ==后台交互==
    saveVo() {
      // permissionService
      this.$refs.dialogForm.validate((errors) => {
        if (!errors) {
          let data = Object.assign({}, this.dialogForm)
          this.dialogFormSaving = true
          roleApi.addRole(data).then(res => {
            // console.log("saveVo", res)
            this.dialogFormSaving = true
            this.close()
            this.reset()
            this.Message.success( "添加成功", { closable: true, duration: 5000 } )
            this.listData()
          }, res => {
            this.dialogFormSaving = true
            this.Message.error( res.message, { closable: true, duration: 5000 } )
          })
        }
      })
    },
    updateVo() {
      // permissionService
      this.$refs.dialogForm.validate((errors) => {
        if (!errors) {
          let data = Object.assign({}, this.dialogForm)
          this.dialogFormSaving = true
          roleApi.updateRole(data).then(res => {
            // console.log("updateVo", res)
            this.dialogFormSaving = false
            this.close()
            this.reset()
            this.Message.success( "更新成功", { closable: true, duration: 5000 } )
            this.listData() // refresh
          }, res => {
            this.dialogFormSaving = false
            this.Message.error( res.message, { closable: true, duration: 5000 } )
          })
        }
      })
    },
    listData() {
      let data = {
        page: this.tablePage.page,
        size: this.tablePage.size,
        param: this.search.name, // name 
      }
      this.tableLoading = true
      roleApi.listRole(data).then( res => {
        // console.log("list", res)
        this.tableLoading = false
        this.tablePage.total = res.data.total
        let arrList =  res.data.list
        this.datas = arrList
        this.tableCheckList = {}
      }, err => {
        this.tableLoading = false
        this.Message.error( err.message, { closable: true, duration: 5000 } )
      })
    },
    deleteVo(vo) {
      this.Dialog.warning({
          title: '警告',
          content: '你确定要删除吗？',
          positiveText: '确定',
          negativeText: '不确定',
          onPositiveClick: () => {
              let data = {
                roleCode: vo.roleCode
              }
              roleApi.delRole(data).then(res => {
                  // console.log("updateVo", res)
                  this.Message.success( "删除成功", { closable: true, duration: 5000 } )
                  this.listData() // refresh
              }, res => {
                  this.Message.error( res.message, { closable: true, duration: 5000 } )
              })
          }
      })
    },

    // ==角色权限部分==
    // 获取完整的权限树
    queryPermissionTree() {
      permissionApi.tree().then(res => {
        this.permissionTree = res.data
      }, err => {
        this.Message.error( err.message, { closable: true, duration: 5000 } )
      })
    },
    clearTree() {
      this.permissionTreeRefreshing = true
      permissionApi.clearTree().then(res => {
        this.permissionTreeRefreshing = false
        this.Message.success( '刷新成功', { closable: true, duration: 3000 } )
        this.queryPermissionTree()
      }, err => {
        this.permissionTreeRefreshing = false
        this.Message.error( err.message, { closable: true, duration: 5000 } )
      })
    },
    // 关闭角色权限视图
    closeRolePermission() {
      this.permissionDialog.visible = false
      this.permissionDialog.saving = false
    },
    // 重置角色权限视图
    resetRolePermission() {
      this.permissionDialog.visible = false
      this.permissionDialog.loading = false
      this.permissionDialog.saving = false
      this.permissionDialog.role = null
      this.permissionDialog.permissionTreeOption = []
      this.permissionDialog.permissions = []
    },
    // 打开权限视图
    async editRolePermissions(role) {
      // console.log("role", role)
      const roleCp = Object.assign({}, role)
      this.permissionDialog.role = roleCp
      

      // 获取角色的权限，重新组装权限树
      await rolePermissionApi.listAllPermissionByRole({ role: role.roleCode })
      .then(res => {
        if(res.data) {
          let originPermissions = res.data.map(e => e.permission+"")
          this.permissionDialog.oldPermissions = [].concat(originPermissions)
          this.permissionDialog.permissions = [].concat(originPermissions)
        } else {
          this.permissionDialog.oldPermissions = []
          this.permissionDialog.permissions = []
        }
        // console.log("role-permissions", this.permissionDialog.oldPermissions)
      }, err => {
        this.Message.error( "无法获取角色的权限！ "+err.message, { closable: true, duration: 5000 } )
      })

      // permissionTreeOption
      this.permissionDialog.permissionTreeOption = convertToTreeOptionArray(this.permissionTree)
      
      // 模态框显示必须放到后面, 不然默认值会不生效
      this.permissionDialog.visible = true
    },
    // 权限选择发生变化
    handleUpdatePermission(selectedKeys, selectedOptions) {
      // 根节点点击全选后， selectedOption只会返回父节点，但可以从父节点中找到所有子节点
      // console.log("args", selectedKeys, selectedOptions)
      let newKeys = getKeysInTreeNodeArr(selectedOptions)
      this.permissionDialog.permissions = newKeys
    },
    // 保存角色权限
    saveRolePermission() {
      // console.log("permissions", this.permissionDialog.permissions)
      let data = { 
        role: this.permissionDialog.role.roleCode,
        permissions: this.permissionDialog.permissions,
       }
       this.permissionDialog.saving = true
      rolePermissionApi.updateRoleAllPermission(data)
      .then(res => {
        this.permissionDialog.saving = false
        this.Message.success( "保存成功", { closable: true, duration: 3000 } )
        this.closeRolePermission()
        this.resetRolePermission()
      }, err => {
        this.permissionDialog.saving = false
        this.Message.error( "保存失败！", { closable: true, duration: 5000 } )
      })
    },
    // 搜索模板选择
    searchData() {
      this.tablePage.page = 1
      this.listData()
    },
    // 刷新角色的权限（主要用于清除后台缓存）
    refreshRolePermission(row) {
      let data = {
        role: row.roleCode
      }

      this.rolePermissionRefreshing = true
      rolePermissionApi.clearRolePermission(data).then(res => {
        this.rolePermissionRefreshing = false
        this.Message.success( '刷新成功', { closable: true, duration: 3000 } )
      }, err => {
        this.rolePermissionRefreshing = false
        this.Message.error( err.message, { closable: true, duration: 5000 } )
      })
    }
  },
}